import * as path from "path";
import * as fs from "fs";
import * as child_process from "child_process";
import * as readline from "readline";

const protoClientDir = path.join(__dirname, "./protoClient"); // 客户端协议目录（服务器没有客户端svn权限，故将协议生成到公用目录，由客户端自己拉取）

console.time("cmd build ok ");
routeBuild(() => {
  console.timeEnd("cmd build ok ");

  console.time("proto build ok ");
  const protoc = path.join(__dirname, "protoc.exe");
  const config_path = path.join(__dirname, "../src/config/proto");
  const dist_path = path.join(__dirname, "../dist/config/proto");

  if (!fs.existsSync(dist_path)) {
    fs.mkdirSync(dist_path, { recursive: true });
  }

  let fileArr = fs.readdirSync(config_path);
  fileArr.forEach((file) => {
    if (!file.endsWith(".proto")) {
      return;
    }
    const basename = path.basename(file, ".proto");
    const proto_file = path.join(config_path, file);
    const dist_dts = path.join(config_path, basename + ".d.ts");
    const dist_js = path.join(dist_path, basename + ".js");

    // js
    const cmd1 = `pbjs -t static-module -w commonjs -o ${dist_js} ${proto_file}`;
    execSync(cmd1);

    // ts
    const cmd2 = `pbts -o ${dist_dts} ${dist_js}`;
    execSync(cmd2);

    // C#
    const cmd3 = `${protoc} -I=${config_path} --csharp_out=${protoClientDir} ${proto_file}`;
    execSync(cmd3);
    //const cmd4 = `${protoc} -I=${config_path} --js_out=${protoClientDir} ${proto_file}`;

    // 客户端协议目录。 注： creator 使用需要将文件中 require("protobufjs/minimal") 替换为 protobuf
    let text = fs.readFileSync(dist_js).toString();
    text = text.replace(`require("protobufjs/minimal")`, `protobuf`);
    fs.writeFileSync(path.join(protoClientDir, path.basename(dist_js)), text);
    fs.copyFileSync(dist_dts, path.join(protoClientDir, path.basename(dist_dts)));
  });

  console.timeEnd("proto build ok ");
});

function execSync(cmd: string) {
  child_process.execSync(cmd);
}

function routeBuild(cb: Function) {
  let routePath = "../src/config/sys/route.ts";
  let serverPath = "../src/config/cmd.ts";

  let filepath = path.join(__dirname, routePath);
  if (!fs.existsSync(filepath)) {
    console.log("  ->  Not find the script: " + filepath);
    process.exit();
  }
  let readStream = fs.createReadStream(filepath);
  let read_route = readline.createInterface({ "input": readStream });

  let hasStart = false;
  let cmdObjArr: { "cmd": string, "note": string }[] = [];

  read_route.on("line", function (line) {
    line = line.trim();
    if (line === "") {
      return;
    }
    if (!hasStart) {
      if (line.indexOf("export") === 0) hasStart = true;
      return;
    }
    if (line.indexOf("]") === 0) {
      serverCmd();
      clientCmd();
      read_route.close();
      return;
    }
    if (line.indexOf('"') !== 0) {
      return;
    }
    line = line.substring(1);
    let index = line.indexOf('"');
    if (index === -1) {
      return;
    }

    let cmd = line.substring(0, index);
    let note = "";
    index = line.indexOf("//");
    if (index !== -1) {
      note = line.substring(index + 2).trim();
    }
    cmdObjArr.push({ "cmd": cmd, "note": note });
  });

  read_route.on("close", function () {
    cb && cb();
  });

  function serverCmd() {
    let endStr = `export const enum cmd {\n`
    let index = 0;
    for (let one of cmdObjArr) {
      if (one.note) {
        endStr += `\t/**\n\t * ${one.note}\n\t */\n`;
      }
      let oneStr = one.cmd;
      if (one.cmd.indexOf('.') !== -1) {
        let tmpArr = one.cmd.split('.');
        oneStr = tmpArr[0] + '_' + tmpArr[1] + '_' + tmpArr[2];
      }
      endStr += `\t${oneStr} = ${index},\n`;
      index++;
    }
    endStr += '}';

    fs.writeFileSync(path.join(__dirname, serverPath), endStr);
  }

  function clientCmd() {
    let endStrCs = 'public class Cmd\n{\n'
    let endStrTs = 'export const enum cmd {\n'
    for (let one of cmdObjArr) {
      if (one.note) {
        endStrCs += `\t/// <summary>\n\t/// ${one.note}\n\t/// </summary>\n`;
        endStrTs += `\t/**\n\t * ${one.note}\n\t */\n`;
      }
      let oneStr = one.cmd;
      if (one.cmd.indexOf('.') !== -1) {
        let tmpArr = one.cmd.split('.');
        oneStr = tmpArr[0] + '_' + tmpArr[1] + '_' + tmpArr[2];
      }
      endStrCs += `\tpublic const string ${oneStr} = "${one.cmd}";\n`;
      endStrTs += `\t${oneStr} = "${one.cmd}",\n`;
    }

    endStrCs += '}';
    endStrTs += '}';

    if (!fs.existsSync(protoClientDir)) {
      fs.mkdirSync(protoClientDir, { recursive: true });
    }
    fs.writeFileSync(path.join(protoClientDir, "cmdClient.ts"), endStrTs);
  }
}
